package com.neuronbit.businessflow.intellij.file;

import com.neuronbit.businessflow.intellij.BpmBundle;
import com.neuronbit.businessflow.intellij.BpmFileType;
import com.neuronbit.businessflow.intellij.BpmLanguage;
import com.neuronbit.businessflow.intellij.lang.PsiBpmFile;
import com.intellij.ide.fileTemplates.CreateFromTemplateHandler;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.JavaTemplateUtil;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;

import java.util.Map;

/**
 * The type Bpm create from template handler.
 */
public class BpmCreateFromTemplateHandler implements CreateFromTemplateHandler {
    @Override
    public boolean handlesTemplate(@NotNull FileTemplate template) {
        FileType fileType = FileTypeManagerEx.getInstanceEx().getFileTypeByExtension(template.getExtension());
        return fileType.equals(BpmFileType.INSTANCE) && !ArrayUtil.contains(template.getName(), JavaTemplateUtil.INTERNAL_FILE_TEMPLATES);
    }

    /**
     * Create class or interface psi bpm file.
     *
     * @param project   the project
     * @param directory the directory
     * @param content   the content
     * @param reformat  the reformat
     * @param fileName  the file name
     * @return the psi bpm file
     * @throws IncorrectOperationException the incorrect operation exception
     */
    public static PsiBpmFile createClassOrInterface(Project project,
                                                    PsiDirectory directory,
                                                    String content,
                                                    boolean reformat,
                                                    String fileName) throws IncorrectOperationException {
        final PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText(fileName, BpmLanguage.INSTANCE, content, false, false);

        if (!(psiFile instanceof PsiBpmFile psiBpmFile)) {
            throw new IncorrectOperationException("This template did not produce a Bpm Flow\n" + psiFile.getText());
        }

        directory.add(psiBpmFile);

        if(reformat){
            CodeStyleManager.getInstance(project).scheduleReformatWhenSettingsComputed(psiBpmFile);
        }

        return psiBpmFile;
    }

    @NotNull
    @Override
    public PsiElement createFromTemplate(@NotNull Project project,
                                         @NotNull PsiDirectory directory,
                                         String fileName,
                                         @NotNull FileTemplate template,
                                         @NotNull String templateText,
                                         @NotNull Map<String, Object> props) throws IncorrectOperationException {
        return createClassOrInterface(project, directory, templateText, template.isReformatCode(), fileName);
    }

    @Override
    public boolean canCreate(final PsiDirectory @NotNull [] dirs) {
        for (PsiDirectory dir : dirs) {
            if (canCreate(dir)) return true;
        }
        return false;
    }


    @Override
    public boolean isNameRequired() {
        return false;
    }


    @NotNull
    @Override
    public String getErrorMessage() {
        return BpmBundle.message("title.cannot.create.flow");
    }

    @Override
    public void prepareProperties(@NotNull Map<String, Object> props) {
        String packageName = (String) props.get(FileTemplate.ATTRIBUTE_PACKAGE_NAME);
        if (packageName == null || packageName.length() == 0) {
            props.put(FileTemplate.ATTRIBUTE_PACKAGE_NAME, FileTemplate.ATTRIBUTE_PACKAGE_NAME);
        }
    }

    @NotNull
    @Override
    public String commandName(@NotNull FileTemplate template) {
        return BpmBundle.message("command.create.flow.from.template");
    }

    /**
     * Can create boolean.
     *
     * @param dir the dir
     * @return the boolean
     */
    public static boolean canCreate(PsiDirectory dir) {
        return JavaDirectoryService.getInstance().getPackage(dir) != null;
    }
}
